#ifndef EDGES_BASE_HPP
#define EDGES_BASE_HPP

#include "crtpBase.hpp"
#include "meshTypes_fwd.hpp"
#include <experimental/memory>

namespace hms
{

/* this is not a forward declaration, but rather the full definition of the
 * unspecialised traits class. Each edges implementation has to specialise it.
 * */
/**
 * @brief Traits class to hold information on types used by the edges class
 * 
 * @tparam MeshType 
 */
template<typename EdgesType>
class EdgesTraits{};

template<class EdgesType>
class EdgesBase : public CrtpBase<EdgesType>
{
public:
	using Traits = EdgesTraits<EdgesType>;
	using MeshType = typename Traits::MeshType;
	using NormalsReturnType = typename Traits::NormalsReturnType;
	using LengthsReturnType = typename Traits::LengthsReturnType;

protected:
	std::experimental::observer_ptr<const MeshType> m_mesh {nullptr};

public:
	auto mesh() const -> const MeshType&;
	void mesh( const MeshType& );

	auto lengths() const -> LengthsReturnType;
	auto normals() const -> NormalsReturnType;
	auto outwardNormals( const BoundaryPatch& ) const -> decltype(auto);

	#ifdef STRUCTMESH_PRECALC_EDGE_PARENT_CELLS
	auto cells(Index order = 1) const -> const Array2Xi&;
	#endif

protected:
	EdgesBase() = default;
	EdgesBase( const MeshBase<MeshType>& );
};

} // namespace hms

#include "edgesBase.tpp"

#endif